I am using d3-format's format function to round some numbers (yes, I know this isn't necessary).
When I format negative numbers, I get a string of a negative number, as expected. However, when I convert it back into a number using the + shorthand, it returns NaN. This is not what should happen. I should get back a regular negative number.
import {format} from "d3-format"; //version 3.1.0
let numberFormatter = d3.format(".3f");
let neg = -2.333;
let negString = "-2.333";
let d3negString = numberFormatter(neg);
//the strings look the same
console.log(d3negString) // "-2.333"
console.log(negString) // "-2.333"
//both strings have the same type of 'string'
console.log(typeof negString === typeof d3negString); // true
//but they are not equal
console.log(negString === d3negString); // false
//normal strings work as expected
console.log(isNaN(+negString)); // false
//but strings from d3-format function returns NaN
console.log(isNaN(+d3negString)); // true
It says that both strings have the same type 'string', however their values are not equal?? Even though the text is equal?
What is the true type of d3-formatted number strings? They can't just be normal strings, right? Why is it returning NaN? Is this a bug?
MacOS Big Sur
Chrome 96.0.4664.110
d3-format@3.1.0
The change log of d3, shows that in version 2.0.0 the following was changed:
Change the default minus sign to the minus sign (−) instead of hyphen-minus (-).
In this thread on D3's github are some interesting comments:
D3 did use the minus sign originally, but people complained about that, too (e.g., #595), primarily because there was an expectation that d3.format would use the same symbol as JavaScript’s
number.toString. The minus sign was thus replaced with hyphen-minus in 2.10.0 (da3131c, #756).
And:
This is now available as an opt-in by specifying the locale’s
minusproperty. And I’m considering making the minus sign the default (again) in the next major version.
The reason this doesn't work is because the 'minus' characters, despite appearing identical, are different unicode symbols.
Luckily, d3 provides a way to change the default minus character to whatever you choose using the formatLocale function.]
'HYPHEN-MINUS' U+002D unicode character is recognized as a 'negative sign'.
// import {format} from 'd3-format' //do not directly import format with default settings
import { formatLocale} from "d3-format"
const format = formatLocale({ minus: "\u002D"}).format
let numberFormatter = d3.format(".3f");
let neg = -2.333;
let negString = "-2.333";
let d3negString = numberFormatter(neg);
console.log(d3negString) // "-2.333"
console.log(negString) // "-2.333"
console.log(typeof negString === typeof d3negString); // true
console.log(negString === d3negString); // true
console.log(isNaN(+negString)); // false
console.log(isNaN(+d3negString)); // false
The larger moral of the story is that d3-format's goal is NOT to round numbers - it is to make number look nice as text. To prevent problems, use Math.round() or "-2.3333".toFixed(3) // => -2.333 to round numbers in javascript.